
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="stylesheet" type="text/css" href="ar.css">
        <script src="./aframe.min.js"></script>
        <script src="./aframe-extras.min.js"></script>
        <script src="./mindar-image-aframe.prod.js"></script>
        <script src="./hybrid_html_uni.webview.1.5.5.js"></script>

        <!-- <script src="https://aframe.io/releases/1.5.0/aframe.min.js"></script>
        <script src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras@v7.0.0/dist/aframe-extras.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/mind-ar@1.2.5/dist/mindar-image-aframe.prod.js"></script> -->
        <script src="./howler.core.js"></script>
        <script>
            const ver = "1.0.211111";
            console.log("---  ver: " + ver);

            var curRegion = '' // 当前听诊区
            
            var mindArImagined = false; // 是否AR识别
           

            
            // 听诊区声音
            var RegionInfo = {
                A: [
                    {
                        text:'正常心音',
                        file:'正常心音'
                    },
                    {
                        text:'A区-1',
                        file:'heart6二尖瓣关闭不全'
                    },
                    {
                        text:'A区-2',
                        file:'heart7二尖瓣狭窄'
                    }
                ],
                P:[
                    {
                        text:'正常心音',
                        file:'正常心音'
                    },
                    {
                        text:'P区-1',
                        file:'heart6二尖瓣关闭不全'
                    },
                    {
                        text:'P区-2',
                        file:'heart7二尖瓣狭窄'
                    }
                ],
                E:[
                    {
                        text:'正常心音',
                        file:'正常心音'
                    },
                    {
                        text:'E区-1',
                        file:'heart6二尖瓣关闭不全'
                    },
                    {
                        text:'E区-2',
                        file:'heart7二尖瓣狭窄'
                    }
                ],
                T:[
                    {
                        text:'正常心音',
                        file:'正常心音'
                    },
                    {
                        text:'T区-1',
                        file:'heart6二尖瓣关闭不全'
                    },
                    {
                        text:'T区-2',
                        file:'heart7二尖瓣狭窄'
                    }
                ],
                M:[
                    {
                        text:'正常心音',
                        file:'正常心音'
                    },
                    {
                        text:'M区-1',
                        file:'heart6二尖瓣关闭不全'
                    },
                    {
                        text:'M区-2',
                        file:'heart7二尖瓣狭窄'
                    }
                ]
            }

            const RegionNames = {
                A:'主动脉瓣区',
                P:'脉动脉瓣区',
                E:'中动脉瓣第二听诊区',
                T:'三尖瓣区',
                M:'二尖瓣区'
            }

            // --  暂停所有音频
            const stopAllSounds = function () {
                const allAudio = document.querySelectorAll('audio');
                allAudio.forEach(function(audioItem) {
                    audioItem.pause();
                });
            };

            const SwitchCamera = (environmentDeviceId)=>{
                window.arSystem.stop();
                window.arSystem.video = document.createElement('video');
                window.arSystem.video.setAttribute('autoplay', '');
                window.arSystem.video.setAttribute('muted', '');
                window.arSystem.video.setAttribute('playsinline', '');
                window.arSystem.video.style.position = 'absolute'
                window.arSystem.video.style.top = '0px'
                window.arSystem.video.style.left = '0px'
                window.arSystem.video.style.zIndex = '-2'
                window.arSystem.container.appendChild(window.arSystem.video);

                if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
                    // TODO: show unsupported error
                    window.arSystem.el.emit("arError", {error: 'VIDEO_FAIL'});
                    window.arSystem.ui.showCompatibility();
                    return;
                }

                navigator.mediaDevices.getUserMedia({audio: false, video: {
                    facingMode: 'environment',
                    deviceId: environmentDeviceId
                }}).then((stream) => {
                    window.arSystem.video.addEventListener( 'loadedmetadata', () => {
                    //console.log("video ready...", this.video);
                    window.arSystem.video.setAttribute('width', window.arSystem.video.videoWidth);
                    window.arSystem.video.setAttribute('height', window.arSystem.video.videoHeight);
                    window.arSystem._startAR();
                });
                    window.arSystem.video.srcObject = stream;
                }).catch((err) => {
                    console.log("getUserMedia error", err);
                    window.arSystem.el.emit("arError", {error: 'VIDEO_FAIL'});
                });
            }

            const regionSelFunc = (region)=>{
                // 听诊区域选择
                if (curRegion == region) return;
                stopAllSounds();
                curRegion = region;
                const fooclickAll = document.querySelectorAll('[fooclick]');
                const tingzhenqigltf = document.querySelector('#tingzhenqigltf');
                tingzhenqigltf.setAttribute("visible", region != '');
                for (let i = 0; i < fooclickAll.length; i++) {
                    fooclickAll[i].setAttribute('material', 'color', fooclickAll[i].id == region + 'Sphere' ? 'yellow' : 'red');
                    // 听诊器在小球位置 z+0.02
                    if(fooclickAll[i].id == region + 'Sphere')
                    {
                        const spPos = fooclickAll[i].getAttribute("position");
                        tingzhenqigltf.setAttribute("position", {x:spPos.x, y:spPos.y, z:spPos.z + 0.05});
                    }
                }
                const operationPanel = document.getElementById('bottom-buttons')
                if (region == '') {
                    // 关闭听诊区
                    operationPanel.style.display='none';
                    
                } else {
                    operationPanel.style.display = 'block';
                    if (!operationPanel.classList.contains("operation-panel-collapsed")) {
                        operationPanel.classList.toggle('operation-panel-collapsed'); // 切换class来展开或收起内容
                    }
                    const operationToggleBtn = document.getElementById('operationToggleBtn')
                    operationToggleBtn.textContent = '折叠'
                    
                    // 删除所有声音
                    const sounds = document.getElementById('sounds');
                    while (sounds.firstChild) {  
                        sounds.removeChild(sounds.firstChild);  
                    }
                    // 添加声音
                    const regionObjs = RegionInfo[region];
                    if (regionObjs) {
                        document.getElementById('title').textContent = RegionNames[region]
                        for (let i = 0; i < regionObjs.length; i++) {
                            const btn = document.createElement('button');
                            btn.textContent = regionObjs[i].text;
                            btn.className = 'bottom-button';
                            sounds.appendChild(btn);
                            btn.addEventListener('click', function() {  
                                stopAllSounds();
                                // 播放声音  
                                document.getElementById(regionObjs[i].file).play().catch(function(error) {  
                                    console.log('播放声音失败:', error);  
                                });  
                            });
                        }
                    }
                    
                }
            }

            

            document.addEventListener("DOMContentLoaded", ()=>{
                const sceneEl = document.querySelector('a-scene');
                let arSystem;
                console.log("sceneEl", sceneEl);

                const typeBtn = document.querySelector("#type-button");
                const resetBtn = document.querySelector("#reset-button");
                // const closeBtn = document.querySelector("#close-btn");
                
                Object.keys(RegionInfo).forEach(function(key) {  
                    for (let i = 0; i < RegionInfo[key].length; i++) {
                        const audio = document.createElement('audio');
                        audio.src = './assets/audio/' + RegionInfo[key][i].file + '.mp3';
                        audio.id = RegionInfo[key][i].file;
                        document.body.appendChild(audio);  
                    }
                
                });
                const loadDivList = document.getElementsByClassName("loader");
                if(loadDivList.length > 0)
                {
                    loadDivList[0].parentElement.classList.remove("hidden");
                }
                // ---    监听模型加载完成  -------------------------------------
                document.querySelector('a-asset-item').addEventListener('loaded', function() { 
                    console.log("heartModel ---  loaded ---  ");
                })

                // 蒙层，点击关闭
                document.getElementById('overlay').addEventListener('click', function(e) {  
                    if (true) {  
                        this.classList.add('overlay-hidden');  
                        const timer = setInterval(()=>{
                            if (window.arSystem && window.isHeartModelLoaded) {
                                window.arSystem.start();
                                clearInterval(timer)
                                console.log(navigator.userAgent);
                                let fallbackDelayTime = 8000;
                                if(navigator.userAgent.indexOf("OpenHarmony") > -1)
                                {
                                    fallbackDelayTime = 10000;
                                    // 鸿蒙手机
                                    setTimeout(()=>{
                                        if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
                                            console.log("enumerateDevices() not supported.");
                                        } else {
                                            navigator.mediaDevices.enumerateDevices()
                                            .then(function(devices) {
                                                console.log("devices",devices);
                                                for (let deviceIndex = 0; deviceIndex < devices.length; deviceIndex++) {
                                                    const deviceElement = devices[deviceIndex];
                                                    if (deviceElement.label == "camera2 2, facing back") {
                                                        console.log("SwitchCamera  devices",deviceElement);
                                                        SwitchCamera(deviceElement.deviceId);
                                                        break;
                                                    }
                                                }
                                                
                                            });
                                        }
                                    }, 2000);
                                }
                                 // 8s 没有识别成功，则自动跳转到3d模式显示
                                setTimeout(()=>{
                                    console.log("setTimeout mindArImagined " , mindArImagined);
                                    console.log("setTimeout window.arSystem", window.arSystem);
                                    console.log("setTimeout window.imageTrackType", window.imageTrackType)
                                    if (mindArImagined == false && window.arSystem && window.imageTrackType == "ar") {
                                        console.log("window.arSystem.stop  =========  切换   " );
                                        mindArFound();
                                        const typeBtn = document.querySelector("#type-button");
                                        // 切换为3D模式
                                        window.arSystem.stop(); // stop AR 
                                        window.imageTrackType = "model";
                                        typeBtn.textContent = "切换AR";
                                        const trackModel = document.querySelector("#heartmodelentity");
                                        trackModel.setAttribute("visible", true);
                                        const heartgltfModel = document.querySelector("#heartgltfmodel");
                                        heartgltfModel.setAttribute("visible", true);
                                        let tempWorldMatrix = [
                                            0.994075133847564,
                                            -0.01036457303610734,
                                            -0.10866754853193954,
                                            0,
                                            0.010024923133073531,
                                            0.9780683736556112,
                                            -0.20783627423769194,
                                            0,
                                            0.10889362050154293,
                                            0.20514968032766615,
                                            0.9726459768822093,
                                            0,
                                            -477.59290898257353,
                                            84.34603241631248,
                                            -3501.6820895587834,
                                            1
                                        ];
                                        window.arSystem.stop();
                                        window.arSystem.ui.hideScanning();
                                        window.arSystem.anchorEntities[1].el.updateWorldMatrix(tempWorldMatrix);
                                        regionSelFunc('')
                                    }
                                }, fallbackDelayTime);
                                
                               
                            }
                        },100);
                    }  
                });

                // app中添加关闭按钮
                const topCloseBtn = document.getElementById('top-close-btn')
                // if (window == window.parent) topCloseBtn.style.display = "none";
                topCloseBtn.addEventListener('click', function(e) {  
                    let info = {
                        data:{
                            action: "back",
                        }
                    }
                    uni && uni.postMessage(info)
                    //window.parent.postMessage(info, "*")
                });

                // 操作面板---展开/收起---动画
                const operationToggleBtn = document.getElementById('operationToggleBtn')
                operationToggleBtn.addEventListener('click', function() {
                    var slider = document.getElementById('bottom-buttons');
                    slider.classList.toggle('operation-panel-collapsed'); // 切换class来展开或收起内容
                    let oldText = operationToggleBtn.textContent
                    operationToggleBtn.textContent = oldText === '展开' ? '折叠' : '展开'
                    stopAllSounds();
                });

                // -- 场景加载完成
                sceneEl.addEventListener('loaded', function () {
                    arSystem = sceneEl.systems["mindar-image-system"];
                    console.log("arsystem", arSystem);
                    window.arSystem = arSystem;
                    let canvasEl = sceneEl.canvas;
                    console.log("canvasEl --  ", canvasEl)
                    if (!canvasEl) {
                        sceneEl.addEventListener('render-target-loaded', this.addEventListeners.bind(this));
                        return;
                    }

                    const loadDivList = document.getElementsByClassName("loader");
                    if(loadDivList.length > 0)
                    {
                        loadDivList[0].parentElement.classList.remove("hidden");
                    }


                    // --    旋转 缩放  ----- 
                    let touchStarted = false;
                    let selfTouchData = {};
                   
                    let onTouchStart = function (evt) {
                        for (let i = 0; i < evt.touches.length; i++) {
                            console.log("-- touch start", evt.touches[i].identifier,"x:"+evt.touches[i].pageX,"y:"+evt.touches[i].pageY);
                            selfTouchData['touch'+ evt.touches[i].identifier] = {x:evt.touches[i].pageX, y:evt.touches[i].pageY}
                        }
                        
                    }
                    const rotateFactor = 2;
                    const maxScale = 6;
                    const minScale = 0.5;
                    modelObject = document.querySelector('#heartgltfmodel');
                    let onTouchMove = function (evt) {
                       

                        if(evt.touches.length == 0) return;
                        else if(evt.touches.length == 1)
                        {
                            // 旋转
                            let rotation = modelObject.object3D.rotation;
                            const currPos = {x:evt.touches[0].pageX, y:evt.touches[0].pageY}
                            const oldPos = selfTouchData['touch' + evt.touches[0].identifier]
                            const deltaPos = {x:currPos.x - oldPos.x, y:currPos.y - oldPos.y}
                            let deltaY = 2 * Math.PI * (deltaPos.x) / canvasEl.clientWidth;
                            let deltaX = 2 * Math.PI * (deltaPos.y) / canvasEl.clientHeight;
                            console.log("-- deltaY ", deltaY, "-- deltaX ", deltaX);
                            console.log( "rotation", rotation);
                            rotation.y -= deltaY * rotateFactor;
                            rotation.x -= deltaX * rotateFactor;
                            modelObject.object3D.rotation = rotation; // .setAttribute("rotation", rotation);
                            selfTouchData['touch' + evt.touches[0].identifier] = currPos;
                        }else if(evt.touches.length == 2)
                        {
                            // 缩放
                            const touch0 = evt.touches[0];
                            const touch1 = evt.touches[1];
                            let oldTouch0 = selfTouchData['touch' + touch0.identifier];
                            let oldTouch1 = selfTouchData['touch' + touch1.identifier];
                            const newTouch0 = {x:touch0.pageX, y:touch0.pageY};
                            const newTouch1 = {x:touch1.pageX, y:touch1.pageY};
                            const oldDistance = Math.sqrt(Math.pow(oldTouch1.x - oldTouch0.x, 2) + Math.pow(oldTouch1.y - oldTouch0.y, 2) );
                            const newDistance = Math.sqrt(Math.pow(newTouch1.x - newTouch0.x, 2) + Math.pow(newTouch1.y - newTouch0.y, 2) );;
                            const scaleOffset = (newDistance - oldDistance)/100;
                            console.log("oldTouch0:"+oldTouch0,"oldTouch1:"+oldTouch1,"newTouch0："+newTouch0,"newTouch1:"+newTouch1,"oldDistance:"+oldDistance,"newDistance:"+newDistance,"scaleOffset:"+scaleOffset);
                            let scale = modelObject.getAttribute("scale"); // 
                            scale = {
                                x:scale.x + scaleOffset,
                                y:scale.y + scaleOffset,
                                z:scale.z + scaleOffset,
                            }
                            console.log("---  scale",scale.x);
    
                            if(scale.x > maxScale)
                            {
                                scale = {x:maxScale, y:maxScale, z:maxScale};
                            }
                            if(scale.x < minScale)
                            {
                                scale = {x:minScale, y:minScale, z:minScale};
                            }
                            console.log(modelObject.getAttribute("scale"), "newScale",scale)
                            modelObject.setAttribute("scale", scale);
                            selfTouchData['touch' + touch0.identifier] = newTouch0;
                            selfTouchData['touch' + touch1.identifier] = newTouch1;
                        }
    
                    }
    
                    let onTouchEnd = function (evt) {
                        console.log("--- touch end", evt);
                        touchStarted = false;
                       
                    }
    
                    canvasEl.addEventListener('touchstart', onTouchStart);
                    canvasEl.addEventListener('touchmove', onTouchMove);
                    canvasEl.addEventListener('touchend', onTouchEnd);
                    canvasEl.addEventListener('cancel', onTouchEnd);
                    // canvasEl.addEventListener('mousedown', onTouchStart);
                    // window.addEventListener('mousemove', onTouchMove);
                    // window.addEventListener('touchend', onTouchEnd);
                    // window.addEventListener('cancel', onTouchEnd);
                })
                
                window.imageTrackType = "ar";
                typeBtn.addEventListener('click', ()=>{
                    if (window.imageTrackType == "ar") {
                        // 切换为3D模式
                        arSystem.stop(); // stop AR 
                        window.imageTrackType = "model";
                        typeBtn.textContent = "切换AR";
                        regionSelFunc('')
                    } else {
                        // 切换为AR模式
                        window.imageTrackType = "ar";
                        const trackModel = document.querySelector("#heartmodelentity");
                        trackModel.setAttribute("visible", false);
                        // const bodyModel = document.querySelector("#bodymodelentity");
                        // bodyModel.setAttribute("visible", false);
                        const heartgltfModel = document.querySelector("#heartgltfmodel");
                        heartgltfModel.setAttribute("visible", false);
                        regionSelFunc('')
                        document.getElementById('top-buttons').style.display = 'none';
                        
                        stopAllSounds();
                        arSystem.start(); // stop AR 
                        typeBtn.textContent = "切换3D";
                        // regionSelFunc('')
                    }
                })
                

                resetBtn.addEventListener('click', () => {
                    const reseyModelObject = document.querySelector('#heartgltfmodel');
                    reseyModelObject.object3D.rotation.x = 0;
                    reseyModelObject.object3D.rotation.y = 0;
                    reseyModelObject.object3D.rotation.z = 0;
                    reseyModelObject.setAttribute("position","0 -0.25 0");
                    reseyModelObject.setAttribute("scale",{x: 2, y: 2, z: 2});
                });

                // closeBtn.addEventListener('click', ()=>{
                //     stopAllSounds();
                //     regionSelFunc('')
                // })

                
                document.getElementById('top-buttons').style.display = 'none';
                document.getElementById('bottom-buttons').style.display = 'none';


                
            })
            
            AFRAME.registerComponent('heattgltfcomp', {
                schema: {},
                init: function () {
                },
                update: function () {},
                tick: function () {
                    
                    if(!window.isHeartModelLoaded )
                    {
                        for (const objChild of this.el.object3D.children) {
                            if(objChild.name == "Scene")
                            {
                                window.isHeartModelLoaded = true;
                                // arSystem.start();
                                break;
                            }
                        }
                        
                    }
                },
                remove: function () {},
                pause: function () {},
                play: function () {
                }
            });


            const mindArFound = ()=>{
                console.log("target found");
                mindArImagined = true;
                document.getElementById('top-buttons').style.display = '';
                let heartGltfModel = document.querySelector('#heartgltfmodel');
                heartGltfModel.setAttribute("visible", true);
                console.log("---  heartGltfModel.object3D ", heartGltfModel.object3D)
                let heartSceneNode = heartGltfModel.object3D.getObjectByName('Scene');
                for (const heartGltfModelChild of heartGltfModel.object3D.children) {
                    if(heartGltfModelChild.name == "Scene")
                    {
                        console.log(heartGltfModelChild);
                        heartSceneNode = heartGltfModelChild;
                        break;
                    }
                }
                const heartSceneChild=["A","P","E","T","M"];
                for (let i = 0; i < heartSceneChild.length; i++) {
                    const cname = heartSceneChild[i];
                    const cnode = heartSceneNode.getObjectByName(cname);
                    if(cnode != null)
                    {
                        let position = new THREE.Vector3();  
                        let matrix = new THREE.Matrix4();  
                        
                        let currentEntity = cnode;  
                        while (currentEntity !== heartSceneNode) {  
                        const el = currentEntity;  
                        matrix.multiplyMatrices(el.matrix, matrix);  
                        currentEntity = el.parent;  
                        }  
                        
                        position.setFromMatrixPosition(matrix);
                        document.getElementById(cname+'Sphere').setAttribute('position', position);
                    }
                    
                }
                


                regionSelFunc('')
                
                document.getElementById('top-buttons').style.display = '';
            }
            AFRAME.registerComponent('mindarcomponent', {
                schema: {},
                init: function () {
                    console.log("mindarcomponent  init ", this.el,"window.arSystem",window.arSystem);

                    let self = this;
                    
                    
                    // detect target found
                    this.el.addEventListener("targetFound", event => {
                        mindArFound();
                    });
                    // detect target lost
                    this.el.addEventListener("targetLost", event => {
                        console.log("target lost");
                        
                        regionSelFunc('')
                        
                        document.getElementById('top-buttons').style.display = 'none';
                    });
                },
                update: function () {},
                tick: function () {},
                remove: function () {},
                pause: function () {},
                play: function () {}
            });
    
            // -----------------   foo click  component  ---------------------------------------------------
            AFRAME.registerComponent('fooclick', {
                schema: {type: 'string'},
                init: function () {
                    console.log("foo click  init ", this.data);
                    let self = this;
                    
                    this.el.addEventListener('click', function (evt) {

                        
                        regionSelFunc(self.data);
                    });
                },
                update: function () {},
                tick: function () {},
                remove: function () {},
                pause: function () {},
                play: function () {}
            });

            
            
        </script>
    </head>
  <body>
    <div id="heart-scanning-overlay" class="hidden"></div>

    <a-scene mindar-image="imageTargetSrc: ./assets/houseband.mind;maxTrack: 2; autoStart: false;"  vr-mode-ui="enabled: false" device-orientation-permission-ui="enabled: false">
        
        <a-camera position="0 0 0" look-controls="enabled: false" cursor="fuse: false; rayOrigin: mouse;" raycaster="near: 10; far: 10000; objects: .clickable"></a-camera>

        <a-assets>
            <a-asset-item id="heartModel" src="./assets/heart/Heartbeat.gltf"></a-asset-item>
            <a-asset-item id="tingzhenqiModel" src="./assets/tingzhenqi/tingzhenqi.gltf"></a-asset-item>
        </a-assets>
        <a-entity id="bodymodelentity" mindarcomponent mindar-image-target="targetIndex: 0"></a-entity>

        <a-entity id="heartmodelentity" mindarcomponent mindar-image-target="targetIndex: 1">
            <a-gltf-model id="heartgltfmodel" heattgltfcomp rotation="0 0 0 " position="0 -0.25 0" scale="2 2 2" src="#heartModel" animation-mixer>
                <a-sphere id="ASphere" fooclick="A" position="0 0 0" class="clickable" color="red" radius="0.015"></a-sphere>
                <a-sphere id="PSphere" fooclick="P" position="0 0.1 0" class="clickable" color="red" radius="0.015"></a-sphere>
                <a-sphere id="ESphere" fooclick="E" position="0 0 0.1" class="clickable" color="red" radius="0.015"></a-sphere>
                <a-sphere id="TSphere" fooclick="T" position="0 0.1 0" class="clickable" color="red" radius="0.015"></a-sphere>
                <a-sphere id="MSphere" fooclick="M" position="0 0 0.1" class="clickable" color="red" radius="0.015"></a-sphere> 
                <a-gltf-model id="tingzhenqigltf" name position="0 0 0" rotation="-90 90 90" visible="false" src="#tingzhenqiModel"></a-gltf-model> 
            </a-gltf-model>
        </a-entity>
        <a-light type="ambient" color="#333"></a-light>
        <a-light color="#DA8" position="1 1 1"></a-light>

    </a-scene>

    <div class="top-container" id="top-buttons">  
        <button id="reset-button" class="top-button">重&nbsp;&nbsp;&nbsp;置</button>  
         <button id="type-button" class="top-button">切换3D</button>  
    </div>
    <button class="close-btn" id="top-close-btn">x</button>
    <!-- 操作区 -->
    <div class="bottom-container" id="bottom-buttons"> 
        <p id="title" class="operation-panel-title">标题</p>
        <button id="operationToggleBtn" class="operation-panel-close">展开</button>
        <div id="sounds" class="operation-panel-content"></div>
    </div>
    <div id="overlay">  
        <div class="overlay-content">  
            <!-- 这里可以添加蒙层上的内容 -->  
            点击任意位置开始扫描
        </div>  
    </div>  
  </body>
  
</html>